package hc.j2me.ui;

import java.io.UnsupportedEncodingException;

import hc.core.ContextManager;
import hc.core.HCTimer;
import hc.core.IConstant;
import hc.core.IPNGScreen;
import hc.core.L;
import hc.core.MsgBuilder;
import hc.core.data.DataInputEvent;
import hc.core.util.LogManager;
import hc.j2me.ScreenClientManager;
import hc.j2me.Starter;

import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.TextBox;
import javax.microedition.lcdui.TextField;
import javax.microedition.lcdui.game.GameCanvas;
import javax.microedition.lcdui.game.Layer;
import javax.microedition.lcdui.game.LayerManager;
import javax.microedition.lcdui.game.Sprite;

public abstract class PNGGameCanvas extends GameCanvas implements IPNGScreen, CommandListener{
	protected Boolean LOCK = new Boolean(false);

	public int locX, locY, BOTTOM_Y, MAX_RIGHT_X;
	public boolean isDragged = false;
//	暂时关闭
	protected final ActionWatcherTimer actionPressWatcher;
	
	public final LayerManager lm = new LayerManager();
	private Image screen;
	protected final Sprite screenSprite;
	protected final Graphics screenGraph;
	private Graphics refreshGraph;

	byte[] targetID;
	protected final short dragPixelBorder;
	protected  TextBox textBox;
	protected PressShortPanel shortPanel;
	
	protected final int _16;
	protected final int userMouseHeightIdx;
	protected final int userMouseWidthIdx;
	protected final int _blockWidth;

	protected final int userMouseSplitWidth = 3;

	public static final short R_OK = 1;
	public static final short R_ERR = -1;
	public static final short R_CANCEL = 0;//中断事件树
	public static final short R_CONTINUE = 2;//继续事件树

	public PNGGameCanvas(final int refreshMS) {
		super(false);
		
		_16 = Starter.getIconSize(ScreenClientManager.getClientWidth(), ScreenClientManager.getClientHeight());
		int _19 = 19;
		userMouseHeightIdx = _19 + _16;
		_blockWidth =  _16 + userMouseSplitWidth * 2;
		userMouseWidthIdx = ScreenClientManager.getClientWidth() - _19 - _16;
		
		screen = Image.createImage(ScreenClientManager.getClientWidth(), ScreenClientManager.getClientHeight());// 10,
		// 10);
		screenGraph = screen.getGraphics();
		screenGraph.setColor(192, 192, 192);
		screenGraph.fillRect(0, 0, screen.getWidth(), screen.getHeight());
		
		screenSprite = new Sprite(screen);		
		

		actionPressWatcher = new ActionWatcherTimer("", 500, false);
		actionPressWatcher.gameCanvas = this;
		
		setFullScreenMode(true);
		
		refreshTimer = new HCTimer("", refreshMS, false) {
			public void doBiz() {
				setEnable(false);
				refreshScreenDirect();
			}
		};
		
		dragPixelBorder = (short)((_16 == 16)?3:6);
	}

	public int actionPointerReleased(int x, int y){
		if(shortPanel.isOn){
			return R_OK;
		}else if(shortPanel.isOnWaitingSelect){
			shortPanel.dispose();
			final int r = shortPanel.pointerReleased(x, y);
			if(r == HCCtrlGameCanvas.R_OK){
				responseActionSound(r, true);
				return R_OK;
			}
		}else{
			actionPressWatcher.endAction();
		}
		return R_CONTINUE;
	}
	
	public void responseActionSound(int done, boolean isDirectRefresh) {
		if (done == 1) {
			Starter.soundOK();
			refreshScreen(isDirectRefresh);
		} else if (done == -1) {
			Starter.soundFail();
		}
	}
	
	protected int pointPressedX, pointPressedY; 
	protected boolean isAutoDraged = false;

	public void actionPointerPressed(int x, int y) {
		if(shortPanel.isOnWaitingSelect){
			shortPanel.dispose();
		}else if(shortPanel.isOn){
			shortPanel.isOn = false;
			shortPanel.isOnWaitingSelect = true;
		}else{
			actionPressWatcher.setEnable(true);
//			L.V = L.O ? false : LogManager.log("starting PressWatcher");
		}
		
		pointPressedX = x;
		pointPressedY = y;

		resetDragTag();

	}

	protected void resetDragTag() {
		isDragged = false;
		isAutoDraged = false;
	}

	public void pointerDragged(final int x, final int y) {
//		L.V = L.O ? false : LogManager.log("Point dragged : x=" + x + ", y=" + y);
		if(isDragged){
			return;
		}else if((x < (pointPressedX - dragPixelBorder) || x > (pointPressedX + dragPixelBorder)) 
				|| (y < (pointPressedY - dragPixelBorder) || y > (pointPressedY + dragPixelBorder))){
			isDragged = true;
		}
	}

	public void popUpShortActionMenu(){		
		shortPanel.isOn = true;
		
		final Sprite sprite_shortclick = shortPanel.sprite_shortclick;
		
		final int halfSpriteHeight = sprite_shortclick.getHeight()/2;
		final int doubleWidth = _blockWidth + _blockWidth;
		final int x = (pointPressedX > doubleWidth)
				?(pointPressedX - doubleWidth):(pointPressedX + _blockWidth);
		final int y = (pointPressedY < halfSpriteHeight)
				?pointPressedY:
					((pointPressedY > (ScreenClientManager.getClientHeight() - halfSpriteHeight))
						?(pointPressedY - sprite_shortclick.getHeight()):(pointPressedY - halfSpriteHeight)
					);
		sprite_shortclick.setPosition(x, y);
		
		shortPanel.pressX = pointPressedX;
		shortPanel.pressY = pointPressedY;
		
		sprite_shortclick.setVisible(true);
		refreshScreenDirect();
	}

	
	public boolean isSameScreenID(final byte[] bs, final int offset, final int len) {
		boolean isSame = true;
		if(len == targetID.length){
			for (int i = 0, j = offset; j < len; ) {
				if(targetID[i++] != bs[j++]){
					isSame = false;
					break;
				}
			}
		}else{
			isSame = false;
		}
		return isSame;
	}

	public final void refreshScreen(final boolean isRefreshNow){
		if(isRefreshNow){
			refreshScreenDirect();
		}else{
			refreshTimer.setEnable(true);
		}
	}

	public final void refreshScreenDirect() {
		if(refreshGraph == null){
			refreshGraph = getGraphics();
		}
		synchronized (LOCK) {
			lm.paint(refreshGraph, 0, 0);
			flushGraphics();
		}
	}

	public final void refreshScreen(final int x, final int y, final int w, final int h) {
		if(refreshGraph == null){
			refreshGraph = getGraphics();
		}
		synchronized (LOCK) {
			lm.paint(refreshGraph, 0, 0);
			flushGraphics(x, y, w, h);
		}
	}

	final HCTimer refreshTimer;

	public void setScreenID(String screenID) {
		try {
			targetID = screenID.getBytes(IConstant.UTF_8);;
		} catch (UnsupportedEncodingException e) {
			targetID = screenID.getBytes();;
		}
	}

	public void showTextUI(String constraints) {
		if (textBox == null) {
			textBox = new TextBox(Starter.getUIString("m02"), "",
					DataInputEvent.MAX_MOBI_UI_TXT_LEN, TextField.ANY);

			// 添加次序不会影响实际排序
			textBox.addCommand(Starter.cmd_ok);
			textBox.addCommand(Starter.cmd_cancel);

			textBox.setCommandListener(this);
		} else {
			textBox.setString("");
		}
//		textBox.setConstraints(TextField.ANY);
		UIManager.pushInAndSwithToNew(textBox);
	}

	public void commandAction(Command c, Displayable disp) {
		if (disp == textBox) {
			if (c == Starter.cmd_ok) {
				DataInputEvent e = new DataInputEvent();
				final byte[] transTxtBS = new byte[MsgBuilder.UDP_BYTE_SIZE];
				
				e.setBytes(transTxtBS);
	
				e.setType(DataInputEvent.TYPE_TRANS_TEXT);
				byte[] txt_bs;
				try {
					txt_bs = textBox.getString().getBytes(IConstant.UTF_8);
				} catch (UnsupportedEncodingException e1) {
					txt_bs = textBox.getString().getBytes();
				}
				e.setTextData(txt_bs, 0, txt_bs.length);
				ContextManager.getContextInstance().send(
						MsgBuilder.E_INPUT_EVENT, transTxtBS, e.getLength());
			} else if (c == Starter.cmd_cancel) {
	
			}

			UIManager.exitOrReturn();
		}
	}
	
	public void exit() {
		final int size = lm.getSize();
		for (int i = size - 1; i >= 0; i--) {
			lm.remove(lm.getLayerAt(i));
		}
		
		shortPanel.canvas = null;

		HCTimer.remove(actionPressWatcher);		
		HCTimer.remove(refreshTimer);
	}

	public static int getLayerIdx(LayerManager lm, Layer layer){
		final int size = lm.getSize();
		for (int i = 0; i < size; i++) {
			if(lm.getLayerAt(i) == layer){
				return i;
			}
		}
		return 0;
	}

}